package com.example.tanloadpic;


import android.graphics.Bitmap;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;

import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;

import static com.example.tanloadpic.utils.constant.FIFO;
import static com.example.tanloadpic.utils.constant.LIFO;
import static com.example.tanloadpic.utils.constant.REQUEST_HANDLE_FAIL;
import static com.example.tanloadpic.utils.constant.REQUEST_HANDLE_SUCCESS;


public class Dispatcher {
    public static final int TASK_COMPLETE = 5;

    private static final int QUEUE = 1;
    private static final int COMPLETE = 0;
    private Handler mMainHandle;
    private static final String THREAD_DISPATCHER_NAME = "thread_dispatcher_name";
    private static final int DISPATCHER_THREAD_PRIORITY = 10;
    public Handler mHandler;
    private DispatcherThread dispatcherThread;
    private ExecutorService mService;
    private List<BitmapHunter> list;


    public Dispatcher(Handler mainHandle, ExecutorService service, int mode) {
        this.mMainHandle = mainHandle;
        dispatcherThread = new DispatcherThread();
        dispatcherThread.start();
        this.mHandler = new DispatcherHandle(dispatcherThread.getLooper(), this);

        this.mService = service;
        list = new ArrayList<>();
        Collections.synchronizedCollection(list);
        mHandler.sendMessage(mHandler.obtainMessage(mode));

    }

    public void doOut(RequestData data) {
        mHandler.sendMessage(mHandler.obtainMessage(QUEUE, data));
    }

    static class DispatcherThread extends HandlerThread {

        public DispatcherThread() {
            super(THREAD_DISPATCHER_NAME, DISPATCHER_THREAD_PRIORITY);
        }
    }


    static class DispatcherHandle extends Handler {
        private final Dispatcher dispatcher;


        /**
         * 要确保是在同一个looper才有意义。
         *
         * @param looper     looper
         * @param dispatcher 分发器
         */
        public DispatcherHandle(@NonNull @org.jetbrains.annotations.NotNull Looper looper, Dispatcher dispatcher) {
            super(looper);
            this.dispatcher = dispatcher;
        }


        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case QUEUE:
                    RequestData data = (RequestData) msg.obj;
                    dispatcher.doQueue(data);
                    break;
                case LIFO:
                    dispatcher.lastInFirstOutDis();
                    break;

                case FIFO:
                    dispatcher.firstInLastOutDis();
                    break;
                case TASK_COMPLETE:
                    dispatcher.completeTask((BitmapHunter) msg.obj);
                    break;
                default:
                    break;

            }


        }
    }

    private void completeTask(BitmapHunter hunter) {
        Bitmap bitmap = hunter.getBitmapResult();
        if (bitmap != null) {
            mMainHandle.sendMessage(mMainHandle.obtainMessage(REQUEST_HANDLE_SUCCESS, hunter));
        } else {
            mMainHandle.sendMessage(mMainHandle.obtainMessage(REQUEST_HANDLE_FAIL, hunter));
        }

    }

    private void lastInFirstOutDis() {
        if (list.size() > 0) {
            BitmapHunter bitmapHunter = (BitmapHunter) list.get(list.size() - 1);

            mService.execute(bitmapHunter);
            list.remove(list.size() - 1);

        }

        mHandler.sendMessage(mHandler.obtainMessage(LIFO));

    }


    private void firstInLastOutDis() {
        if (list.size() > 0) {
            BitmapHunter bitmapHunter = (BitmapHunter) list.get(0);
            mService.execute(bitmapHunter);
            list.remove(0);
        }
        mHandler.sendMessage(mHandler.obtainMessage(FIFO));

    }

    private void doQueue(RequestData data) {
        BitmapHunter bitmapHunter = new BitmapHunter(data, TanLoadPic.instance, TanLoadPic.instance.mDispatcher);

        list.add(bitmapHunter);


    }


}
